// Copyright (c) 2024 CHANGLEI. All rights reserved.

part of '../../core.dart';

class TooltipRenderArgs {
  TooltipRenderArgs(this.header, this.text, this.location);

  String? text;

  String? header;

  Offset? location;
}

enum TooltipAlignment { near, center, far }

enum DataMarkerType {
  circle,
  rectangle,
  image,
  pentagon,
  verticalLine,
  horizontalLine,
  diamond,
  triangle,
  invertedTriangle,
  none,
}

void drawCircle(Path path, double x, double y, double width, double height) {
  path.addArc(Rect.fromLTRB(x - width / 2, y - height / 2, x + width / 2, y + height / 2), 0, 2 * math.pi);
}

void drawRectangle(Path path, double x, double y, double width, double height) {
  path.addRect(Rect.fromLTRB(x - width / 2, y - height / 2, x + width / 2, y + height / 2));
}

void drawPentagon(Path path, double x, double y, double width, double height) {
  const int eq = 72;
  double xValue;
  double yValue;
  for (int i = 0; i <= 5; i++) {
    xValue = width / 2 * math.cos((math.pi / 180) * (i * eq));
    yValue = height / 2 * math.sin((math.pi / 180) * (i * eq));
    i == 0 ? path.moveTo(x + xValue, y + yValue) : path.lineTo(x + xValue, y + yValue);
  }
  path.close();
}

void drawVerticalLine(Path path, double x, double y, double width, double height) {
  path.moveTo(x, y + height / 2);
  path.lineTo(x, y - height / 2);
}

void drawInvertedTriangle(Path path, double x, double y, double width, double height) {
  path.moveTo(x + width / 2, y - height / 2);

  path.lineTo(x, y + height / 2);
  path.lineTo(x - width / 2, y - height / 2);
  path.lineTo(x + width / 2, y - height / 2);
  path.close();
}

void drawHorizontalLine(Path path, double x, double y, double width, double height) {
  path.moveTo(x - width / 2, y);
  path.lineTo(x + width / 2, y);
}

void drawDiamond(Path path, double x, double y, double width, double height) {
  path.moveTo(x - width / 2, y);
  path.lineTo(x, y + height / 2);
  path.lineTo(x + width / 2, y);
  path.lineTo(x, y - height / 2);
  path.lineTo(x - width / 2, y);
  path.close();
}

void drawTriangle(Path path, double x, double y, double width, double height) {
  path.moveTo(x - width / 2, y + height / 2);
  path.lineTo(x + width / 2, y + height / 2);
  path.lineTo(x, y - height / 2);
  path.lineTo(x - width / 2, y + height / 2);
  path.close();
}

Size measureText(String textValue, TextStyle textStyle, [int? angle]) {
  Size size;
  final TextPainter textPainter = TextPainter(
      textAlign: TextAlign.center, textDirection: TextDirection.ltr, text: TextSpan(text: textValue, style: textStyle),);
  textPainter.layout();

  if (angle != null) {
    final Rect rect = rotatedTextSize(textPainter.size, angle);
    size = Size(rect.width, rect.height);
  } else {
    size = Size(textPainter.width, textPainter.height);
  }
  return size;
}

Rect rotatedTextSize(Size size, int angle) {
  final Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
  final vector.Matrix2 rotatorMatrix = vector.Matrix2.rotation(degreeToRadian(angle));

  final Rect movedToCenterAsOrigin = rect.shift(-rect.center);

  Offset topLeft = movedToCenterAsOrigin.topLeft;
  Offset topRight = movedToCenterAsOrigin.topRight;
  Offset bottomLeft = movedToCenterAsOrigin.bottomLeft;
  Offset bottomRight = movedToCenterAsOrigin.bottomRight;

  topLeft = transform(rotatorMatrix, topLeft);
  topRight = transform(rotatorMatrix, topRight);
  bottomLeft = transform(rotatorMatrix, bottomLeft);
  bottomRight = transform(rotatorMatrix, bottomRight);

  final List<Offset> rotOffsets = <Offset>[topLeft, topRight, bottomLeft, bottomRight];

  final double minX = rotOffsets.map((offset) => offset.dx).reduce(math.min);
  final double maxX = rotOffsets.map((offset) => offset.dx).reduce(math.max);
  final double minY = rotOffsets.map((offset) => offset.dy).reduce(math.min);
  final double maxY = rotOffsets.map((offset) => offset.dy).reduce(math.max);

  final Rect rotateRect = Rect.fromPoints(
    Offset(minX, minY),
    Offset(maxX, maxY),
  );
  return rotateRect;
}

double degreeToRadian(int deg) => deg * (math.pi / 180);

vector.Vector2 offsetToVector2(Offset offset) => vector.Vector2(offset.dx, offset.dy);

Offset vector2ToOffset(vector.Vector2 vector) => Offset(vector.x, vector.y);

Offset transform(
  vector.Matrix2 matrix,
  Offset offset,
) {
  return vector2ToOffset(matrix * offsetToVector2(offset));
}

int getMaxLinesContent(String? text) {
  return text != null && text.isNotEmpty && text.contains('\n') ? text.split('\n').length : 1;
}
